package cn.hengzq.orange.redis.config;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Slf4j
@EnableCaching
@AutoConfiguration
public class RedisCacheAutoConfiguration {

    @Bean
    public RedisCacheConfiguration redisCacheConfiguration() {
        return RedisCacheConfiguration.defaultCacheConfig()
                // 设置缓存默认过期时间
                .entryTtl(Duration.ofMinutes(60))
                // 使用 JSON 序列化 value（对象）
                .serializeValuesWith(
                        RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer(createObjectMapper()))
                )
                ;
    }

    private ObjectMapper createObjectMapper() {
        // 创建 ObjectMapper 并注册 Java 8 时间模块
        ObjectMapper objectMapper = new ObjectMapper();
        //支持 LocalDateTime
        objectMapper.registerModule(new JavaTimeModule());
        // 禁用将日期/时间写成时间戳（否则 LocalDateTime 会变成数组或时间戳）
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

        //  设置日期格式（可选：如果你希望输出为字符串格式）
        // 注意：JavaTimeModule 默认使用 ISO 格式，我们可以通过 DateTimeFormatter 自定义
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));

        objectMapper.activateDefaultTyping(
                LaissezFaireSubTypeValidator.instance, // 允许所有非 final 类的自动类型识别
                ObjectMapper.DefaultTyping.NON_FINAL, // 对所有非 final 类启用类型信息
                JsonTypeInfo.As.PROPERTY // 类型信息以 @class 字段写入 JSON
        );
        return objectMapper;

    }
}
